package com.oritsh.dicom.scp;

import com.oritsh.dicom.scu.DicomStreamStore;
import org.dcm4che.data.Attributes;
import org.dcm4che.data.Tag;
import org.dcm4che.data.VR;

import org.dcm4che.net.*;
import org.dcm4che.net.pdu.PresentationContext;
import org.dcm4che.net.service.BasicCEchoSCP;
import org.dcm4che.net.service.BasicCStoreSCP;
import org.dcm4che.net.service.DicomServiceException;
import org.dcm4che.net.service.DicomServiceRegistry;


import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * Created by xiashenpin on 16/1/31.
 */
public class StoreSCP extends DicomSCP {

    private static final String PART_EXT = ".part";

    private Device device;
    private final ApplicationEntity ae = new ApplicationEntity("*");
    private final Connection conn = new Connection();
    private int status;
    private String aeTitle;

    private DicomStreamStore dicomStreamStore;

    ExecutorService executorService = Executors.newCachedThreadPool();
    ScheduledExecutorService scheduledExecutorService =
            Executors.newSingleThreadScheduledExecutor();

    private final BasicCStoreSCP cstoreSCP = new BasicCStoreSCP("*") {

        @Override
        protected void store(Association as, PresentationContext pc,
                             Attributes rq, PDVInputStream data, Attributes rsp)
                throws IOException {
            rsp.setInt(Tag.Status, VR.US, Status.Success);
            if (dicomStreamStore == null)
                return;

            String iuid = rq.getString(Tag.AffectedSOPInstanceUID);
            String cuid = rq.getString(Tag.AffectedSOPClassUID);
            String tsuid = pc.getTransferSyntax();
            try {
                dicomStreamStore.store(as, as.createFileMetaInformation(iuid, cuid, tsuid), data);
            } catch (Exception e) {
                throw new DicomServiceException(Status.ProcessingFailure, e);
            }

        }

    };


    public StoreSCP(String aeTitle, int port) {

        conn.setPort(port);

        device = new Device(aeTitle);

        device.setDimseRQHandler(createServiceRegistry());
        device.addConnection(conn);
        device.addApplicationEntity(ae);

        ae.addTransferCapability(
                new TransferCapability(null,
                        "*",
                        TransferCapability.Role.SCP,
                        "*"));

        ae.setAssociationAcceptor(true);
        ae.addConnection(conn);


        device.setScheduledExecutor(scheduledExecutorService);
        device.setExecutor(executorService);


    }


    private DicomServiceRegistry createServiceRegistry() {
        DicomServiceRegistry serviceRegistry = new DicomServiceRegistry();
        serviceRegistry.addDicomService(new BasicCEchoSCP());
        serviceRegistry.addDicomService(cstoreSCP);
        return serviceRegistry;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public void bind() throws IOException, GeneralSecurityException {
        device.bindConnections();
    }

    public void bind(int port) throws IOException, GeneralSecurityException {
        conn.setPort(port);
        bind();
    }

    public DicomStreamStore getDicomStreamStore() {
        return dicomStreamStore;
    }

    public void setDicomStreamStore(DicomStreamStore dicomStreamStore) {
        this.dicomStreamStore = dicomStreamStore;
    }

    public String getAeTitle() {
        return aeTitle;
    }

    @Override
    public void close() throws Exception {
        if (device != null) {
            device.unbindConnections();
        }

    }
}
